<?php

class AFWebElement extends AFQueriable
{
	private $name = NULL;

	private $properties = array();

	private $children = array();

	static $uncollapsable = array('script', 'div', 'span', 'p');

	public $html = '';

	public $topLevel = TRUE;

	private $_sysId = NULL;

	private static $_lastSysId = 0;

	private $events = array(
		'_onclick' => array(),
		'_onfoo' => array()
	);

	public function __construct($name)
	{
		$this->name = FN::slug($name);
		$this->_sysId = ++self::$_lastSysId;
	}

	public function getSysId()
	{
		return $this->_sysId;
	}

	public function equals($otherElement)
	{
		return $this->_sysId == $otherElement->getSysId();
	}

	public function queryHandler($name, $arguments)
	{
//		echo $name.count($arguments)." ";
		$name = preg_replace_callback('/([a-z])([A-Z])/', function($matches){
			return $matches[1].'-'.strtolower($matches[2]);
		}, $name);
		if($name[0] == '_')
		{
			// Event query
//			if(!isset($this->events[$name]))
//			{
//			}
			$this->events[$name] = array_merge($this->events[$name], $arguments);
		}
		else
		{
			// Property query
			if(count($arguments))
			{
				$this->properties[$name] = $arguments[0];
			}
			else
			{
				//throw new AFException('', 0);
				//FN::stop();
				//return '123';
	//			echo $this->properties[$name];
				return isset($this->properties[$name]) ? $this->properties[$name] : NULL;
			}
		}
	}

	public function htmlQuery($arguments)
	{
		if(count($arguments))
		{
			$this->children = array();
			$this->html = $arguments[0];
			return $this;
		}
		else
		{
			return $this->html;
		}
	}

	public function topLevelQuery($arguments)
	{
		if(count($arguments))
		{
			$this->topLevel = $arguments[0];
			return $this;
		}
		else
		{
			return $this->topLevel;
		}
	}

//	public function styleQuery()
//	{
//	}

	public function addClass($class)
	{
		$this->properties['class'] = (isset($this->properties['class']) && $this->properties['class']) ? $this->properties['class'] . ' ' . $class : $class;
		return $this;
	}

//	public function removeClass($name)
//	{
//	}

	public function append(/* ... */)
	{
		foreach(func_get_args() as $child)
		{
			if(!($child instanceOf AFWebElement))
			{
				$el = new AFWebElement('span');
				$el->topLevel(FALSE);
				$el->html($child);
				$this->children[] = $el;
				if(func_num_args() == 1)
				{
					return $el;
				}
			}
			else
			{
				$this->children[] = $child;
				if(func_num_args() == 1)
				{
					return $child;
				}
			}
		}
	}

	private function isCollapsable()
	{
		return !in_array($this->name, self::$uncollapsable);
	}

	private function compileProperties()
	{
		return join(' ', array_map(function($parameter, $value){
			// Generate key="value" pairs
			return $parameter . '=' . '"'. htmlspecialchars($value) .'"';
		}, array_keys($this->properties), $this->properties));
	}

	public function render($depth = 0)
	{
		$indent = str_repeat("\t", $depth);
		$innerData = $this->html ? $indent . "\t" . $this->html . "\n" : '';
		foreach($this->children as $child)
		{
			// Render all childs recursively
			$innerData .= $child->render($depth + 1);
		}

/*		if(!$innerData)
		{
			// Nothing found inside
			if($this->isCollapsable())
			{
				return '<' . $this->name . ';
			}
		}*/

//		$indent2 = str_repeat("\t", $depth)."\t";

		if(!$innerData && $this->isCollapsable())	// Nothing inside AND element can be collapsed
		{
//			$chunks = array($this->name);
//			$properties = $this->compileProperties;
//			
			return $indent . '<' . $this->name . (($properties = $this->compileProperties()) ? ' '.$properties : '') . ' sysid="'.$this->_sysId.'" />' . "\n";
		}
		else
		{
			return $indent . '<' . $this->name . (($properties = $this->compileProperties()) ? ' '.$properties : '') . ' sysid="'.$this->_sysId.'">' . (
				$innerData
					?
						"\n" . $innerData . $indent
					:
						''
			) . '</' . $this->name . '>' . "\n";
		}
	}

	public function find()
	{
//		return call_user_func_array(array($this, 'children'), func_get_args());
	}

	public function children(/* $searchKey = 'id', $value */)
	{
		if(func_num_args() == 1)
		{
			$searchKey = 'id';
			$value = func_get_arg(0);
		}
		else if(func_num_args() == 2)
		{
			$searchKey = func_get_arg(0); 
			$value = func_get_arg(1);
		}

		$found = array();

		foreach($this->children as $child)
		{
			if($child->$searchKey() == $value)
			{
				$found[] = $child;
			}
		}
		return new AFCollection($found);
	}

	public function _find()
	{
	}

	public function newElement($name)
	{
		$el = new AFWebElement($name);
		$el->topLevel(FALSE);
		$this->append($el);
	}

	public function removeChild($childToRemove)
	{
		foreach($this->children as $key => $child)
		{
			if($childToRemove->equals($childToRemove))
			{
				unset($this->children[$key]);
			}
		}
	}

	public function triggerEvents($group)
	{
		foreach($this->events[$group] as $event)
		{
			$event($this);
		}
	}

/*	public function renderAsDocument()
	{
		$doc = new AFWebDocument();
		$this->
	}*/
}

?>
